package cn.itcast.nems.journal.util;

import cn.hutool.core.lang.Assert;
import cn.itcast.ic.common.exception.v2.BizExceptionProducer;
import cn.itcast.nems.common.enumeration.NemsErrorBodyEnum;
import cn.itcast.nems.common.util.NumberUtil;
import cn.itcast.nems.manager.util.CustomBeanUtil;
import cn.itcast.nems.oldems.dto.Refund;
import cn.itcast.nems.oldems.dto.StudentDto;
import cn.itcast.nems.order.dao.entity.JournalRefund;
import cn.itcast.nems.order.dao.entity.JournalRefundFinance;
import cn.itcast.nems.order.dao.entity.JournalRefundRollback;
import cn.itcast.nems.order.dto.OrderMode;
import cn.itcast.nems.studentrecord.dao.entity.StudentRecord;
import cn.itcast.nems.studentrecord.dto.refund.JournalRefundClazzDTO;
import cn.itcast.nems.studentrecord.dto.refund.JournalRefundDTO;
import cn.itcast.nems.studentrecord.dto.refund.JournalRefundRollbackDTO;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Objects;

public class JournalRefundUtil {
    private static  final Logger log = LoggerFactory.getLogger(JournalRefundUtil.class)  ;
    public static ObjectMapper OBJECT_MAPPER  ;

    private JournalRefundUtil () {}

    static {
        JavaTimeModule timeModule  =new JavaTimeModule() ;
        timeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        timeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        OBJECT_MAPPER = new ObjectMapper()
                .setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE)
                .configure(JsonGenerator.Feature.IGNORE_UNKNOWN, true)
                .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
                .registerModule(timeModule) ;
    }

    /**
     * <p>
     * 生成同步EMS【退费凭单】参数对象
     * </p>
     *
     * @param orderRefund 退费表单数据
     * @author zhouwei
     * @since 2024/3/25 3:07 PM
     **/
    public static Refund convertToRefund(JournalRefund orderRefund ,
                                         JournalRefundFinance journalRefundFinance ,
                                         String schoolCode ) {
        Refund refund =new Refund() ;
        // 收入支出类别（退费方式）, IncomeExpensesType表id
        refund.setIncomeExpensestype(Integer.parseInt(journalRefundFinance.getCostTypeId()));
        // 退费手续费, 单位:元
        refund.setRefundCommission(NumberUtil.convertToYuan(journalRefundFinance.getCharge())) ;
        // 退费凭单头-退费金额
        refund.setCost(NumberUtil.convertToYuan(-orderRefund.getAmount()));
        // 先存学籍ID ， 调用EMS接口之前会替换成 老EMS studentjoinclazz 表 id
        refund.setJoinclassid(orderRefund.getStudentRecordId());
        // 收据号
        refund.setAcquittanceno(journalRefundFinance.getReceiptNo());
        // pos交易号，刷pos机的编号
        refund.setPosNo(journalRefundFinance.getPosNo());
        // 贷款公司, 枚举参看备注
        refund.setFinanceCorporation(orderRefund.getLoanCompany());
        // 费用发生日期 -- 对应补充表单的付款时间
        // refund.setFinancetime(orderRefund.getBizDate());
        refund.setFinancetime(journalRefundFinance.getPaymentDatetime());
        // 老EMS 登记时间
        refund.setLogTime(journalRefundFinance.getBizDate());
        refund.setPaymentchannel(journalRefundFinance.getPaymentAccountCode());
        // 学生缴费（方式）如：现金，贷款，刷卡等；退费（类型）。student_cost_type表的name字段
        refund.setStudentCostType(orderRefund.getRefundTypeName());
        // 凭证号
        refund.setVoucherno(journalRefundFinance.getPaymentNo());
        // 校区code
        refund.setSchoolCode(schoolCode);
        return   refund ;
    }
    /**
     * <p>
     * 生成同步EMS 【退费退回】参数对象
     * </p>
     *
     * @param orderRefund 退费表单数据
     * @author zhouwei
     * @since 2024/3/25 3:07 PM
     **/
    public static Refund convertToRefund(JournalRefund orderRefund ,
                                         JournalRefundFinance journalRefundFinance,
                                         JournalRefundRollback refundRollback,
                                         String schoolCode ) {
        Refund refund =new Refund() ;
        // 收入支出类别（退费方式）, IncomeExpensesType表id
        refund.setIncomeExpensestype(Integer.parseInt(journalRefundFinance.getCostTypeId()));
        // 退费手续费, 单位:元
        refund.setRefundCommission(null) ;
        // 退费退回金额 (正数)
        refund.setCost(NumberUtil.convertToYuan(refundRollback.getAmount()));
        // 先存学籍ID ， 调用EMS接口之前会替换成 老EMS studentjoinclazz 表 id
        refund.setJoinclassid(orderRefund.getStudentRecordId());
        // 收据号  退费退回表单没有
        // refund.setAcquittanceno(refundRollback.getBizNo());
        // pos交易号，刷pos机的编号
        refund.setPosNo(refundRollback.getPosNo());
        // 贷款公司, 枚举参看备注
        refund.setFinanceCorporation(orderRefund.getLoanCompany());
        // 费用发生日期 -- 对应补充表单的付款时间
        // refund.setFinancetime(orderRefund.getBizDate());
        refund.setFinancetime(refundRollback.getRollbackDatetime());
        // 老EMS 登记时间
        refund.setLogTime(LocalDateTime.now());
        // 支付渠道
        refund.setPaymentchannel(refundRollback.getPaymentAccountCode());
        // 学生缴费（方式）如：现金，贷款，刷卡等；退费（类型）。student_cost_type表的name字段
        refund.setStudentCostType(orderRefund.getRefundTypeName());
        // 凭证号 退费退回表单没有
        // refund.setVoucherno(journalRefundFinance.getPaymentNo());
        // 校区code
        refund.setSchoolCode(schoolCode);
        return   refund ;
    }



    public static void validateJournalRollbackDTO(JournalRefundRollbackDTO refundRollbackDTO) {
        Assert.notNull(refundRollbackDTO ,BizExceptionProducer.produce(NemsErrorBodyEnum.DATA_EXIST ,"请求参数")) ;
        Assert.notNull(refundRollbackDTO.getRollbackDatetime() , BizExceptionProducer.produce(NemsErrorBodyEnum.PARAM_EMPTY, "退费日期")) ;
    }

    public  static JournalRefundDTO convert(JournalRefund refund , StudentRecord studentRecord ,
                                            OrderMode orderMode, Integer studentId, StudentDto student) {
        JournalRefundDTO refundDTO    = CustomBeanUtil.copyProperties(refund ,new JournalRefundDTO()) ;
        refundDTO.setAmount(NumberUtil.convertToYuan(refund.getAmount()));
        JournalRefundClazzDTO refundClazzDTO = new JournalRefundClazzDTO() ;
        refundClazzDTO.setClazzId(studentRecord.getClazzId());
        refundClazzDTO.setRefundAmount(NumberUtil.convertToYuan(studentRecord.getRefundAmount()));
        refundClazzDTO.setAdjustmentAmount(NumberUtil.convertToYuan(studentRecord.getAdjustmentAmount()));
        refundClazzDTO.setInDate(studentRecord.getInDate());
        refundClazzDTO.setSettlementDate(studentRecord.getSettlementDate());
        refundClazzDTO.setDiscountAmount(NumberUtil.convertToYuan(studentRecord.getDiscountAmount()));
        refundClazzDTO.setTransferFromAmount(NumberUtil.convertToYuan(studentRecord.getTransferFromAmount()));
        refundClazzDTO.setPaidAmount(NumberUtil.convertToYuan(studentRecord.getPaidAmount()));
        refundClazzDTO.setStudentRecordId(studentRecord.getId());
        refundClazzDTO.setClazzName(refund.getClazzName());
        refundClazzDTO.setPrice(NumberUtil.convertToYuan(studentRecord.getPrice()));
        // 学生ID
        refundClazzDTO.setStudentId(studentId);
        // 支付方式
        if(Objects.nonNull(orderMode)) {
            refundClazzDTO.setPaymentTypeId(orderMode.getPaymentTypeId());
            refundClazzDTO.setPaymentTypeName(orderMode.getPaymentTypeName());
        }
        refundDTO.setList( List.of(refundClazzDTO) );
        refundDTO.setStudentId(student.getId());
        refundDTO.setStudentName(student.getName());
        refundDTO.setStudentNo(student.getNumber());
        return refundDTO ;
    }

    public static Boolean validateSuspensionForm(JournalRefundFinance journalRefundFinance) {
        if(Objects.isNull(journalRefundFinance)) {
            log.warn("【审批补充表单】表单对象为空");
            return false ;
        }
        if (!StringUtils.hasText(journalRefundFinance.getCompanyCode())) {
            log.warn("【审批补充表单】所属公司code为空");
            return false;
        }
        if (!StringUtils.hasText(journalRefundFinance.getCompanyName())) {
            log.warn("【审批补充表单】所属公司name为空");
            return false;
        }
        if (!StringUtils.hasText(journalRefundFinance.getCostTypeId())) {
            log.warn("【审批补充表单】费用类型ID为空");
            return false;
        }
        if (!StringUtils.hasText(journalRefundFinance.getCostTypeName())) {
            log.warn("【审批补充表单】费用类型name为空");
            return false;
        }
        if (!StringUtils.hasText(journalRefundFinance.getPaymentAccountCode())) {
            log.warn("【审批补充表单】付款渠道code为空");
            return false;
        }
        if (!StringUtils.hasText(journalRefundFinance.getPaymentAccountName())) {
            log.warn("【审批补充表单】付款渠道name为空");
            return false;
        }
        if (Objects.isNull(journalRefundFinance.getPaymentDatetime())) {
            log.warn("【审批补充表单】付款时间为空");
            return false;
        }
        if (Objects.isNull(journalRefundFinance.getBizDate())) {
            log.warn("【审批补充表单】办理时间为空");
            return false;
        }
        if (!StringUtils.hasText(journalRefundFinance.getCreatedBy())) {
            log.warn("【审批补充表单】退款操作人为空");
            return false;
        }
        return true;
    }
}
